/**
 * Copyright 2016 JustWayward Team
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.x.service.api;

import com.x.service.BuildConfig;
import com.x.service.entity.AutoComplete;
import com.x.service.entity.Base;
import com.x.service.entity.BookDetail;
import com.x.service.entity.BookList;
import com.x.service.entity.CatsList;
import com.x.service.entity.Chapter;
import com.x.service.entity.ChaptersInfo;
import com.x.service.entity.DeviceInfo;
import com.x.service.entity.HotWord;
import com.x.service.entity.RangeList;
import com.x.service.entity.TagList;
import com.x.service.entity.Version;
import com.x.service.entity.map.ChapterReadToChapter;
import com.x.zssqservice.bean.ChapterRead;

import okhttp3.OkHttpClient;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.functions.Func1;

/**
 * https://github.com/JustWayward/BookReader
 *
 * @author yuyh.
 * @date 2016/8/3.
 */
public class BookApi implements DataRepository {
    ChapterReadToChapter chapterReadToChapter = new ChapterReadToChapter();

    public static BookApi instance;

    private BookApiService service;

    public BookApi(OkHttpClient okHttpClient) {
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(BuildConfig.API_SERVER)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rx适配器
                .addConverterFactory(GsonConverterFactory.create()) // 添加Gson转换器
                .client(okHttpClient)
                .build();
        service = retrofit.create(BookApiService.class);
    }

    public static BookApi getInstance(OkHttpClient okHttpClient) {
        if (instance == null)
            instance = new BookApi(okHttpClient);
        return instance;
    }

    @Override
    public Observable<BookList> getRecommendList(String bookId) {
        return service.getRecommendList(bookId).concatMap(bookList -> precessError(bookList));
    }

    <R extends Base> Observable<R> precessError(R base) {
        return Observable.create(new Observable.OnSubscribe<R>() {
            @Override
            public void call(Subscriber<? super R> subscriber) {
                if (base.errorCode != 0) {
                    base.ok = false;
                    subscriber.onError(new APIException(base.errorCode, base.message));
                }
                base.ok = true;
                subscriber.onNext(base);
                subscriber.onCompleted();
            }
        });
    }

    @Override
    public Observable<BookDetail> getBookDetial(String bookId) {
        return service.getBookDetial(bookId).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<BookList> getBooksByTag(TagList.Tag tag, int start, int limit) {
        return service.getBookByCat(tag._id, start, limit).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<BookList> getBooksByAuthor(String author, int start, int limit) {
        return service.getBooksByAuthor(author, start, limit).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<BookList> searchBook(String query, int start, int limit) {
        return service.searchBook(query, start, limit).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<AutoComplete> autoComplete(String query) {
        return service.autoComplete(query).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<HotWord> getHotWord() {
        return service.getHotWord().concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<ChaptersInfo> getChapters(String bookId) {
        return service.getChapters(bookId).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<Chapter> getChapterRead(String link) {
        return service.getChapterRead(link).concatMap(new Func1<ChapterRead, Observable<? extends Chapter>>() {
            @Override
            public Observable<? extends Chapter> call(ChapterRead chapterRead) {
                return Observable.create(new Observable.OnSubscribe<Chapter>() {
                    @Override
                    public void call(Subscriber<? super Chapter> subscriber) {
                        subscriber.onNext(chapterReadToChapter.map(chapterRead));
                        subscriber.onCompleted();
                    }
                });
            }
        });
    }

    @Override
    public Observable<TagList> getTagLst() {
        return service.getTagLst().concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<CatsList> getCatList() {
        return service.getCatList().concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<BookList> getBookByCat(CatsList.Cat cat, int start, int limit) {
        return service.getBookByCat(cat.id, start, limit).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<RangeList> getRangelist() {
        return service.getRangelist().concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<BookList> getBooksByRangeId(String id) {
        return service.getBooksByRangeId(id).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<Base> reportDerice(DeviceInfo deviceInfo) {
        return service.reportDerice(deviceInfo).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<Version> getVersion(String channelId) {
        return service.getVersion(channelId).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<Base> addToLib(String token, String book) {
        return service.addToLib(token, book).concatMap(bookList -> precessError(bookList));
    }

    @Override
    public Observable<BookList> getBooksByIds(String bookId) {
        return service.getBooksByIds(bookId).concatMap(bookList -> precessError(bookList));
    }
}
